<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      //   function Animal() {
      //     this.type = "动物";
      //   }

      //   Animal.prototype.say = () => {
      //     alert("所有的动画都会叫");
      //   };

      //   function Dog(n) {
      //     // Animal.call(this);
      //     Animal.apply(this);
      //     this.name = n;
      //   }
      //   Dog.prototype.wang = function () {
      //     alert("小狗汪汪汪");
      //   };

      //   let dahuang = new Dog("大黄");
      //   alert(dahuang.type);
      // 1.第一种继承方法 构造函数继承 用call和apply继承，这个继承只能继承父类构造函数里的属性和方法 ，原型上的不能继承

      //   function Animal() {
      //     this.type = "动物";
      //   }

      //   Animal.prototype.say = () => {
      //     alert("所有的动画都会叫");
      //   };

      //   function Dog(n) {
      //     this.name = n;
      //   }
      //   Dog.prototype = Animal.prototype;
      //   Dog.prototype.wang = function () {
      //     alert("小狗汪汪汪");
      //   };

      //   let dahuang = new Dog("大黄");
      //   alert(dahuang.type);
      //   dahuang.say();
      //2.第二种继承是原型继承 这个的缺点是只能继承父类的原型上的方法和属性 构造函数里的不能继承

      //   3.组合继承  第一种和第一种和合体 原型继承+构造函数继承

      function Animal() {
        this.type = "动物";
      }

      Animal.prototype.say = () => {
        alert("所有的动画都会叫");
      };

      function Dog(n) {
        this.name = n;
      }
      Dog.prototype = new Animal();

      Dog.prototype.constructor = Dog;
      //   把父类的实例给子类的原型,因为修改原型后constructor的指向变了，我们需要手动变为正确的

      Dog.prototype.wang = function () {
        alert("小狗汪汪汪");
      };
      let xiaohuang = new Dog("小黄");
      //   console.log(xiaohuang.type);
      xiaohuang.say();

      //   4.实例继承把父类的实例给子类的原型,因为修改原型后constructor的指向变了，我们需要手动变为正确的，这种继承属性和方法都能实现继承
    </script>
  </body>
</html>
